在前面一篇文章使用 marked 解析 markdown中,大致介绍了一下 marked 使用过程中的一些问题,今天又再次遇到 ETPL 的 markdown 过滤器嵌套带来的问题。
遇见问题
这次,我想在 table 的 td 里面写 markdown ,期望效果看起来像是这样的:
而 markdown 代码,我是这样写的:
然后出来的效果是这样:
注意黑色的那段代码块,没缩进了!
什么情况?为啥会没缩进呢?
初步分析
仔细一看 markdown 代码,发现里面出现了过滤器嵌套,也就是说,里面那块 markdown 代码会被处理两次!
尝试解决方案1
既然处理了两次,那么就得想办法只处理一次,于是将 markdown 代码改成这样:
看起来每个 markdown 块都只被处理了一次,应该可以了吧!
于是,我得到了这个效果:
这个看起来好像没啥问题了。
但是,结合 filter 代码:
1 2 3 4 5 6 7 8
| var etpl = require('etpl'); var marked = require('marked'); etpl.addFilter('markdown', function (source, useExtra) { source = source.replace(/(^\n+|\n+$)/g, ''); var uselessSpaceCount = source.match(/^\s*/)[0].length; source = source.replace(new RegExp('^ {' + uselessSpaceCount + '}', 'gm'), ''); return marked(source); });
|
发现:第三个 <!– filter: markdown() –> 会导致自己的 markdown 块缩进出问题。
尝试解决方案2
再来仔细玩味一下内嵌 filter 的处理流程吧,希望能找到解决方案。
经过各种 debug ,发现整个处理流程是这样的:
- 1、先处理最里面的 markdown 块(这是是 ETPL 的处理流程),然后生成对应的 HTML 代码,替换掉之前的 markdown 代码;
- 2、再处理外层的 markdown 块,这个块包含了第一步中生成的 HTML 代码块。于是在替换每行空格的时候,同样会替换掉第一步中生成的 code 标签中每一行前面相应的空格。
好了,现在为啥缩进会出问题的原因已经具体定位了,咋办呢?
在第2步调用 marked 解析之前,完全可以把第一步中生成的 HTML 代码拿出来,这样第2步处理的时候就不会去掉 code 块中的有用空格了。这样一来,过滤器关键部分的代码就变成了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var renderer = new marked.Renderer(); require('etpl').addFilter('markdown', function (source, useExtra) { var nestMarkdowns = []; source = source.replace(/<div class="markdown">(.|\n)*<\/div>/g, function (match) { nestMarkdowns.push(match); return '${nestMarkdown}'; }); source = source.replace(/^\n+/, ''); var uselessSpaceCount = source.match(/^\s*/)[0].length; source = source.replace(new RegExp('^ {' + uselessSpaceCount + '}', 'gm'), ''); return '<div class="markdown">' + marked(source, {renderer: renderer}) .replace(/\${nestMarkdown}/g, function () { return nestMarkdowns.shift(); }) + '</div>'; });
|
刷一下页面,再看,符合预期,完全正常!